package tchatcorba.tchat;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;

import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;

import tchatcorba.ClientInterface;
import tchatcorba.ClientInterfaceHelper;
import tchatcorba.Message;
import tchatcorba.ServeurInterfacePOA;



/**
 * Tchat en Corba
 * @author Toto
 * @version 1.0
 */
public class ServeurImpl extends ServeurInterfacePOA {


	ORB orb;
	
	/**
	 * Table stockant pour chaque utilisateur, la ref de son objet distant
	 */
	private HashMap<String, ClientInterface> clients;

	
	/**
	 * 
	 */
	public ServeurImpl(ORB orb) {
		super();
		clients = new HashMap<String, ClientInterface>();
		this.orb = orb;
	}


	/**
	 *
	 */
	public void enregistrer(String pseudo) {
		ClientInterface client = null;

		try
		{
			//Recuperation de la reference de l'objet mandataire (proxy) du service de nommage 
			org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
			NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
			//Recuperation de la reference du servant grace au service de nommage 
			String name = pseudo;
			client = ClientInterfaceHelper.narrow(ncRef.resolve_str(name));
		} 
		catch (InvalidName e) {
			e.printStackTrace();
		} catch (NotFound e) {
			e.printStackTrace();
		} catch (CannotProceed e) {
			e.printStackTrace();
		} catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
			e.printStackTrace();
		} 

		synchronized(clients)
		{
			// Ajoute le nom de l'utilisateur et l'URL du client distant
			clients.put(pseudo,client);
		}

		Message m = new Message();
		m.emetteur = "Serveur";
		m.message = "nouveau participant : "+pseudo;
		m.date = recupHeure();
		
		// Envoie un message aux clients distants pour dire qui est entre dans le chat
		envoyerMessage(m);

		m.emetteur = "Serveur";
		m.message = "Bienvenue ";
		m.date = recupHeure();
		// Envoie un message de bienvenue au nouveau client distant
		envoyerMessageUnique(m, pseudo);

		// Message de log
		System.out.println(pseudo+" enregistre");
			
	}


	
	/**
	 * Recuperation de la date actuelle
	 * @return
	 */
	private String recupHeure() {
		return new Date().toString();
	}

	
	

	/**
	 * 
	 */
	public void desenregistrer(String s) {

		synchronized(clients)
		{
			// Supprime le client nom s
			clients.remove(s);
		}

		// Message de log
		System.out.println(s+" supprime");

		Message m = new Message();
		m.emetteur = "Serveur";
		m.message = s+" est parti";
		m.date = recupHeure();
		
		// Envoie un message aux clients distants pour dire qui a quitte le chat
		envoyerMessage(m);
	}
	


	/**
	 * 
	 */
	public String[] getUtilisateurs() {
		String[] users = new String[clients.size()];
		synchronized(clients)
		{
			users = clients.values().toArray(users);
		}
		return users;
	}


	/**
	 * 
	 */
	public synchronized void envoyerMessage(Message m) {
		Iterator<String> iterateur = null;
		ClientInterface client = null;
		String utilisateur = null;

		synchronized(clients)
		{
			// Recuperer l'ensemble des pseudos des clients enregistres
			iterateur = clients.keySet().iterator();
		}

		// Envoie le message a tous les clients distants
		while(iterateur.hasNext())
		{
			// Recupere la ref de l'objet du client
			utilisateur = (String)iterateur.next();

			synchronized(clients)
			{
				client = clients.get(utilisateur);		
			}

			try {
				// Affiche le message chez le client distant
				client.afficherMessage(m);
			}
			catch(Exception e)
			{
				// Desenregistre un client distant absent
				System.err.println(" utilisateur absent");
				//desenregistrer(utilisateur);//** a finir **//
			}
		}

	}


	/**
	 * 
	 */
	public void envoyerMessageUnique(Message m, String user) {

		Iterator<String> iterateur = null;
		ClientInterface client = null;
		String utilisateur = null;

		synchronized(clients)
		{
			// Recuperer l'ensemble des pseudos des clients enregistres
			iterateur = clients.keySet().iterator();
		}

		// Parcours des clients
		while(iterateur.hasNext())
		{
			// Recupere la ref de l'objet du client
			utilisateur = (String)iterateur.next();

			if(utilisateur.equals(user)) {
				break;
			}

			utilisateur = null;
		}

		// Si echec du message prive alors on previent l'emetteur
		if((utilisateur == null) && !m.emetteur.equals("Serveur"))
		{
			Message m2 = new Message();
			m2.emetteur = "Serveur";
			m2.message = utilisateur + " inconnu";
			m2.date = recupHeure();
			envoyerMessageUnique(m2, m.emetteur);
			return;
		}

		// Cas du serveur
		if(utilisateur == null)
			return;


		// Recuperer une reference pour le client distant associe a cette adresse
		synchronized(clients)
		{
			client = clients.get(user);
		}

		try
		{
			// Affiche le message chez le client distant
			client.afficherMessage(m);
		}
		catch(Exception e)
		{
			// Desenregistre un client distant absent
			System.err.println(" absent");
			desenregistrer(user);
		}

	}


}
